package cn.com.anysdk.core.util;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.StringJoiner;

/**
 * HTTP工具类
 */
public class HttpUtils {
    private static final int CONNECT_TIMEOUT = 5000;
    private static final int READ_TIMEOUT = 10000;
    private static final String USER_AGENT = "AnySDK/1.0";

    private HttpUtils() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 发送GET请求
     *
     * @param url 请求URL
     * @return 响应内容
     */
    public static String get(String url) {
        return get(url, null);
    }

    /**
     * 发送GET请求
     *
     * @param url 请求URL
     * @param headers 请求头
     * @return 响应内容
     */
    public static String get(String url, Map<String, String> headers) {
        try {
            HttpURLConnection conn = createConnection(url, "GET");
            if (headers != null) {
                headers.forEach(conn::setRequestProperty);
            }
            return handleResponse(conn);
        } catch (IOException e) {
            throw new RuntimeException("HTTP GET request failed: " + e.getMessage(), e);
        }
    }

    /**
     * 发送POST请求
     *
     * @param url 请求URL
     * @param body 请求体
     * @return 响应内容
     */
    public static String post(String url, String body) {
        return post(url, body, null);
    }

    /**
     * 发送POST请求
     *
     * @param url 请求URL
     * @param body 请求体
     * @param headers 请求头
     * @return 响应内容
     */
    public static String post(String url, String body, Map<String, String> headers) {
        try {
            HttpURLConnection conn = createConnection(url, "POST");
            conn.setDoOutput(true);
            if (headers != null) {
                headers.forEach(conn::setRequestProperty);
            }
            if (body != null) {
                conn.getOutputStream().write(body.getBytes(StandardCharsets.UTF_8));
            }
            return handleResponse(conn);
        } catch (IOException e) {
            throw new RuntimeException("HTTP POST request failed: " + e.getMessage(), e);
        }
    }

    /**
     * 发送PUT请求
     *
     * @param url 请求URL
     * @param body 请求体
     * @return 响应内容
     */
    public static String put(String url, String body) {
        return put(url, body, null);
    }

    /**
     * 发送PUT请求
     *
     * @param url 请求URL
     * @param body 请求体
     * @param headers 请求头
     * @return 响应内容
     */
    public static String put(String url, String body, Map<String, String> headers) {
        try {
            HttpURLConnection conn = createConnection(url, "PUT");
            conn.setDoOutput(true);
            if (headers != null) {
                headers.forEach(conn::setRequestProperty);
            }
            if (body != null) {
                conn.getOutputStream().write(body.getBytes(StandardCharsets.UTF_8));
            }
            return handleResponse(conn);
        } catch (IOException e) {
            throw new RuntimeException("HTTP PUT request failed: " + e.getMessage(), e);
        }
    }

    /**
     * 发送DELETE请求
     *
     * @param url 请求URL
     * @return 响应内容
     */
    public static String delete(String url) {
        return delete(url, null);
    }

    /**
     * 发送DELETE请求
     *
     * @param url 请求URL
     * @param headers 请求头
     * @return 响应内容
     */
    public static String delete(String url, Map<String, String> headers) {
        try {
            HttpURLConnection conn = createConnection(url, "DELETE");
            if (headers != null) {
                headers.forEach(conn::setRequestProperty);
            }
            return handleResponse(conn);
        } catch (IOException e) {
            throw new RuntimeException("HTTP DELETE request failed: " + e.getMessage(), e);
        }
    }

    /**
     * 构建URL参数
     *
     * @param params 参数Map
     * @return URL参数字符串
     */
    public static String buildUrlParams(Map<String, String> params) {
        if (params == null || params.isEmpty()) {
            return "";
        }
        StringJoiner joiner = new StringJoiner("&");
        params.forEach((key, value) -> joiner.add(key + "=" + value));
        return joiner.toString();
    }

    /**
     * 创建HTTP连接
     *
     * @param url 请求URL
     * @param method 请求方法
     * @return HTTP连接
     */
    private static HttpURLConnection createConnection(String url, String method) throws IOException {
        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
        conn.setRequestMethod(method);
        conn.setConnectTimeout(CONNECT_TIMEOUT);
        conn.setReadTimeout(READ_TIMEOUT);
        conn.setRequestProperty("User-Agent", USER_AGENT);
        conn.setRequestProperty("Accept", "application/json");
        conn.setRequestProperty("Content-Type", "application/json");
        return conn;
    }

    /**
     * 处理HTTP响应
     *
     * @param conn HTTP连接
     * @return 响应内容
     */
    private static String handleResponse(HttpURLConnection conn) throws IOException {
        try {
            int responseCode = conn.getResponseCode();
            if (responseCode >= 200 && responseCode < 300) {
                return readInputStream(conn.getInputStream());
            } else {
                String errorMessage = readInputStream(conn.getErrorStream());
                throw new IOException("HTTP request failed with response code " + responseCode + ": " + errorMessage);
            }
        } finally {
            conn.disconnect();
        }
    }

    /**
     * 读取输入流内容
     *
     * @param inputStream 输入流
     * @return 内容字符串
     */
    private static String readInputStream(InputStream inputStream) throws IOException {
        if (inputStream == null) {
            return "";
        }
        byte[] buffer = new byte[1024];
        int bytesRead;
        StringBuilder response = new StringBuilder();
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            response.append(new String(buffer, 0, bytesRead, StandardCharsets.UTF_8));
        }
        return response.toString();
    }
}